home *** CD-ROM | disk | FTP | other *** search
/ Packard Bell - Internet on a CD / internet on a cd.cdr / Internet / sites / Clementine_NASA / clemdcmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-16  |  17.2 KB  |  528 lines

  1. /*************************************************************************     
  2. *                   ----------------
  3. *                   |  CLEMDCMP    |
  4. *                   ----------------
  5. *
  6. *_TITLE CLEMDCMP Decompress clementine image into various formats
  7. *_DESC  CLEMDCMP will decompress a clementine image and format it into 
  8. *       one of three possible formats:
  9. *       1) decompressed pds image file, with pds labels, the historgram
  10. *           object, and an image object, either the browse image or
  11. *           the full image
  12. *       2) decompressed image file, no labels
  13. *       3) decompressed gif image
  14. *       4) decompressed tiff image
  15. *
  16. *       CLEMDCMP has four command-line arguments.  The first argument
  17. *       indicates the output format of the decompressed image and
  18. *       the following are the options:
  19. *         -p = decompressed pds image file
  20. *         -n = decompressed unlabeled file
  21. *         -t = decompressed tiff file
  22. *         -g = decompressed gif file
  23. *       The second argument indicates which image object to output:
  24. *         -i = full resolution image
  25. *         -b = browse image
  26. *       The third argument is the filename of the input compressed clementine 
  27. *         data file.
  28. *       The fourth argument is the filename of the output decompressed
  29. *         clementine image.
  30. *
  31. *_HIST  Aug 27 1994  Tracie Sucharski, USGS, Flagstaff Original Version
  32. *
  33. **************************************************************************/
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38.  
  39. #include "pds.h"
  40.  
  41. #define MM_TYPE 0x4D4D
  42. #define II_TYPE 0x4949
  43. #define BLKSIZE 32768L
  44.  
  45. main(int argc, char *argv[])
  46. {
  47.   int c;                         /* character for command-line arguments */
  48.   char format;                   /* Output file format */
  49.   char img;                      /* Output image or browse image */
  50.   char infile[128];              /* Input file name */
  51.   char outfile[128];             /* Output file name */
  52.   long lines;                    /* Number of lines and sample of image */
  53.   long samps;
  54.   int  i;                       
  55.   FILE *fpi, *fpo;               /* Input and output file pointers */
  56.   int ret;                       /* Return code */
  57.   char b[2];
  58.   short int *j;
  59.   char bitord;
  60.   unsigned int k, nblocks, rem;
  61.   
  62.   PDSINFO *p;
  63.  
  64.   int labmod(char *text, char img, char bitord);
  65.   int writetif(FILE *fp, long nl, long ns, CHARH *buf, char bitord);
  66.  
  67.  
  68.  
  69.   for (i = 1; i < argc; i++) {
  70.     if (argv[i][0] == '-') {
  71.     argv[i][1] = tolower(argv[i][1]);
  72.     switch (argv[i][1]) {
  73.       case 'p': case 'n': case 'g': case 't':
  74.     format = argv[i][1];
  75.     break;
  76.       case 'i': case 'b':
  77.     img = argv[i][1];
  78.     break;
  79.       default:
  80.     printf("ERROR:CLEMDCMP-Illegal option chosen %c\n", c);
  81.     exit(1);
  82.       }
  83.   }
  84.     else
  85.       break;
  86.   }
  87.  
  88.   if (argc-i != 2) {
  89.     printf("ERROR:CLEMDCMP-You must specify an input and output file\n");
  90.     exit(1);
  91.   }
  92.  
  93. /*************************************************************************
  94. *  Default is to output the full image in pds format
  95. *************************************************************************/
  96.   if (format == '\0') format = 'p';
  97.   if (img == '\0') img = 'i';
  98.  
  99.  
  100.   strcpy(infile, argv[i]);
  101.   strcpy(outfile, argv[i+1]);
  102.  
  103.  
  104. /************************************************************************
  105. *  Determine the bit order
  106. ************************************************************************/
  107.  
  108.   j = (short int *) b;
  109.   b[0] = 1;
  110.   b[1] = 0;
  111.   if (*j == 1) bitord = 'l';
  112.   else bitord = 'm';
  113.  
  114.  
  115. /****************************************************************************
  116. *  The following call will open the compressed Clementine image and create
  117. *  a structure containing the file objects.
  118. ****************************************************************************/
  119.   p = PDSR(infile, &lines, &samps);
  120.  
  121. /****************************************************************************
  122. *  If user chooses to output the browse image, make sure it exists.
  123. ****************************************************************************/
  124.   if (img == 'b' && !(p->brw_imag)) {
  125.     printf("ERROR:CLEMDCMP-This file does not contain a browse image");
  126.     exit(1);
  127.   }
  128.  
  129. /******************************************************************************
  130. *  Open output file
  131. ******************************************************************************/
  132.   fpo = fopen(outfile, "wb");
  133.  
  134. /*****************************************************************************
  135. *  For the pds formatted option, the labels will need to be modified before 
  136. *  writing out.  The uncompressed output file will either be the image or 
  137. *  the browse image, so the pointer to the browse image will be deleted, 
  138. *  and the image pointer will be modified to point to the start of the data.  
  139. *  The pointer to the histogram will also need to be modified.  The 
  140. *  ENCODING_COMPRESSION_RATIO will no longer be applicable, so the value is 
  141. *  changed to "N/A". 
  142. ******************************************************************************/
  143.   if (format == 'p') {
  144.     printf("Writing PDS labeled file.\n");
  145.     if (labmod(p->text, img, bitord) < 0) {
  146.       printf("ERROR:CLEMDCMP-Error reformatting labels");
  147.       exit(1);
  148.     }
  149.     fwrite(p->text, strlen(p->text), 1, fpo);
  150.   }
  151.  
  152. /*****************************************************************************
  153. *  If the output is a pds file write the histogram data followed by the image 
  154. *  data, either the browse image or the full image.  If the output is an
  155. *  unlabeled image file,  write only the image data out.
  156. *****************************************************************************/
  157.   if (format == 'p') fwrite(p->hist, sizeof(long), 256, fpo);
  158.  
  159.   if (format=='p' || format=='n') {
  160.     if (format=='n') printf("Writing raw unlabeled file.\n");
  161.  
  162.     if (img == 'i') {
  163. #ifdef __TURBOC__
  164.       nblocks = (lines*samps) / BLKSIZE;
  165.       rem = (lines*samps) % BLKSIZE;
  166.       for (k=0; k<nblocks; k++, p->image+=BLKSIZE)
  167.     fwrite(p->image,1,BLKSIZE,fpo);
  168.       if ( rem > 0 )
  169.     fwrite(p->image,1,rem,fpo);
  170. #else
  171.       fwrite(p->image, lines*samps, 1, fpo);
  172. #endif
  173.       if (format=='p')printf("PDS labeled file was successfully written.\n");
  174.       if (format=='n') {
  175.         printf("Raw unlabeled file was successfully written.\n");
  176.     printf("\nThe size of the raw image created is %ld lines "
  177.                "by %ld samples with no\n header or label data.\n\n", 
  178.                lines, samps);
  179.       }
  180.     }
  181.  
  182.     if (img == 'b') {
  183.       fwrite(p->brw_imag, p->browse_nrows*p->browse_ncols, 1, fpo);
  184.  
  185.       if (format=='p')printf("PDS labeled file was successfully written.\n");
  186.       if (format=='n') {
  187.     printf("Raw unlabeled file was successfully written..\n");
  188.     printf("\n\nThe size of the raw image created is %ld lines "
  189.            "by %ld samples with no\n header or label data.\n\n", 
  190.            p->browse_nrows, p->browse_ncols);
  191.       }
  192.     }
  193.  
  194.   }
  195.  
  196.  
  197.  
  198.   if (format == 't') {    /*  TIFF format  */
  199.     printf("Writing TIF file.\n");
  200.     if (img == 'i') {
  201.       if (writetif(fpo, lines, samps, p->image, bitord) < 0) {
  202.     printf("ERROR:CLEMDCMP-Error writing full image in tiff format");
  203.     exit(1);
  204.       }
  205.     }
  206.  
  207.     if (img == 'b') {  /* Write browse image */
  208.       if (writetif(fpo, p->browse_nrows, p->browse_ncols, p->brw_imag, bitord) < 0) {
  209.     printf("ERROR:CLEMDCMP-Error writing browse image in tiff format");
  210.     exit(1);
  211.       }
  212.     }
  213.     printf("TIF file was successfully written.\n");
  214.   }
  215.  
  216.   if (format == 'g')  {   /*  GIF format  */
  217.     if (img == 'i') {
  218.       if (writegif(fpo, lines, samps, p->image) < 0) {
  219.     printf("ERROR:CLEMDCMP-Error writing full image in gif format");
  220.     exit(1);
  221.       }
  222.     }
  223.  
  224.     if (img == 'b') {
  225.       if (writegif(fpo, p->browse_nrows, p->browse_ncols, p->brw_imag) < 0) {
  226.     printf("ERROR:CLEMDCMP-Error writing browse image in gif format");
  227.     exit(1);
  228.       }
  229.     }
  230.   }    
  231.  
  232.   
  233.   fclose(fpo);
  234.   exit(0);
  235. }
  236.  
  237.  
  238.  
  239.  
  240.  
  241. int labmod(char *text, char img, char bitord)
  242. /*****************************************************************************
  243. *
  244. *_TITLE  LABMOD - modify the clementine label to reflect the decompression
  245. *
  246. *_ARGS    Type    Variable     I/O  Description
  247. *_PARM    char    *text;        I   Pointer to clementine label
  248. *_PARM    char    img           I   Image Type (Full image or browse image)
  249. *_PARM    char    bitord        I   Bit order of current machine
  250. *_PARM    int     *ret          O   Return code
  251. *                                   0 - OK
  252. *
  253. *_DESC  LABMOD will modify the clementine label to reflect the decompression,
  254. *       and the possible rearranging of the browse image and image object.
  255. *
  256. *_HIST  Apr 13 1994 Tracie Sucharski, USGS, Flagstaff Original Version
  257. *       Jun 27 1994 Tracie Sucharski,  Fixed bug when writing out the
  258. *                       browse image.
  259. *       Jul 14 1994 Tracie Sucharski,  Changed output value of ENCODING_
  260. *                       TYPE keyword.
  261. *       Aug 23 1994 Tracie Sucharski,  Added NOTE to image object if the
  262. *                       output image is the browse image,  also correct
  263. *                       the DATA_TYPE keyword in the histogram object
  264. *                       to indicate the correct byte order.
  265. *
  266. ****************************************************************************/
  267. {
  268.     int lbllen;                     /* Length of incoming label */
  269.     int nlbllen;                    /* Length of outgoing label */
  270.     char *start, *end;              /* Index pointers */
  271.     char sdummy[17];
  272.     int nc;                         /* Number of characters */
  273.     char byte[4];                   /* Starting bytes of objects */
  274.     int hbyte;                      /* Starting byte of Image Historgram */
  275.     int ibyte;                      /* Starting byte of Image */
  276.     int bbyte;                      /* Starting byte of Browse Image */
  277.     int diff;                       /* Difference in bytes between input */
  278.                                     /* label and output label */
  279.     char *labels;                   /* Temporary buffer to hold labels */
  280.  
  281.  
  282.     lbllen = strlen(text);
  283.     labels = (char *)malloc(lbllen);
  284.  
  285.     start = strstr(text, "^IMAGE_HISTOGRAM ");
  286.     sscanf(start, "%s = %d", sdummy, &hbyte);
  287.  
  288.     start = strstr(text, "^IMAGE ");
  289.     sscanf(start, "%s = %d", sdummy, &ibyte);
  290.  
  291.     start = strstr(text, "^BROWSE_IMAGE ");
  292.     sscanf(start, "%s = %d", sdummy, &bbyte);
  293.  
  294. /****************************************************************************
  295. *  Get rid of pointer to browse image.
  296. ****************************************************************************/
  297.     end = strchr(start,'\n');
  298.     strcpy(start, end+1);
  299.  
  300. /***************************************************************************
  301. *  If browse image is being written, get rid of IMAGE object, rename
  302. *  BROWSE_IMAGE object to IMAGE and add a note to indicate the output
  303. *  image is the browse image.
  304. ***************************************************************************/
  305.     if (img == 'b') {
  306.       start = strstr(text, "OBJECT = IMAGE\n");
  307.       end = strstr(start, "END_OBJECT");
  308.       strcpy(start, end+11);
  309.  
  310.       start = strstr(text, " BROWSE_IMAGE");
  311.       end = strchr(start, '\n');
  312.       strncpy(labels, text, (start-text)+1);
  313.       *(labels+(start-text+1)) = '\0';
  314.       strcat(labels, "IMAGE");
  315.       strcat(labels, end);
  316.       strcpy(text, labels);
  317.  
  318.       end = strstr(start, "END_OBJECT");
  319.       strncpy(labels, text, (end-text)+1);
  320.       *(labels+(end-text)) = '\0';
  321.       strcat(labels, "  NOTE          = \"Averaged subsampled EDR image\"\n");
  322.       strcat(labels, end);
  323.       strcpy(text, labels);
  324.  
  325.     }
  326.  
  327.     if (img == 'i') {
  328.  
  329. /**************************************************************************
  330. *  Get rid of the BROWSE_IMAGE object.
  331. ***************************************************************************/
  332.       start = strstr(text, "OBJECT = BROWSE_IMAGE");
  333.       end = strstr(start, "END_OBJECT");
  334.       strcpy(start, end+11);
  335.  
  336. /***************************************************************************
  337. *  If writing IMAGE object change ENCODING_COMPRESSION_RATIO and
  338. *  ENCODING_TYPE keyvalues to "N/A", since the output file is uncompressed.
  339. ***************************************************************************/
  340.       start = strstr(text, "ENCODING_TYPE ");
  341.       end = strchr(start, '\n');
  342.       strncpy(labels, text, (end-text)-1);
  343.       *(labels+(end-text-1)) = '\0';
  344.       strcat(labels, " DECOMPRESSED\"");
  345.       strcat(labels, end);
  346.       strcpy(text, labels);
  347.  
  348.       start = strstr(text, "ENCODING_COMPRESSION_RATIO ");
  349.       end = strchr(start, '\n');
  350.       strncpy(labels, text, (start-text)+29);
  351.       *(labels+(start-text+29)) = '\0';
  352.       strcat(labels, "\"N/A\"");
  353.       strcat(labels, end);
  354.       strcpy(text, labels);
  355.  
  356.     }
  357.  
  358. /****************************************************************************
  359. *  If the bitorder is MSB which is different from that in the label(LSB),
  360. *  change the label.
  361. ****************************************************************************/
  362.     if (bitord == 'm') {
  363.       start = strstr(text, "LSB_INTEGER");
  364.       *start = 'M';
  365.     }
  366.  
  367. /****************************************************************************
  368. *  Adjust the object pointers.
  369. ****************************************************************************/
  370.     nlbllen = strlen(text);
  371.     hbyte = nlbllen + 1;
  372.     ibyte = hbyte + 1024;
  373.  
  374. /*****************************************************************************
  375. *  Now that there are new pointer values, write them out to the labels.
  376. *****************************************************************************/
  377.     sprintf(byte, "%d", hbyte);
  378.     nc = strlen(byte);
  379.     start = strstr(text, "^IMAGE_HISTOGRAM ");
  380.     strncpy(start+19, byte, nc);
  381.  
  382.     sprintf(byte, "%d", ibyte);
  383.     nc = strlen(byte);
  384.     start = strstr(text, "^IMAGE ");
  385.     strncpy(start+19, byte, nc);
  386.  
  387.     free(labels);
  388.     return(0);
  389.  
  390. }
  391.  
  392.     
  393.  
  394. /*************************************************************************
  395. *                       ------------
  396. *                       | WRITETIF |
  397. *                       ------------
  398. *
  399. *_TITLE  WRITETIF  Writes decompressed Clementine data into TIF format
  400. *
  401. *_DESC   WRITETIF takes decompressed Clementine data and writes an 
  402. *        uncompressed TIF formatted image.
  403. *
  404. *_HIST   May 04 1994  Tracie Sucharski, USGS, Flagstaff Original Version
  405. *
  406. *************************************************************************/
  407.  
  408. int writetif(FILE *fp, long nl, long ns, CHARH *buf, char bitord)
  409. {
  410.   unsigned int j, nblocks, rem; /* Added by Luis Perez 06/29/94 */
  411.  
  412.   int fputword(FILE *fp, short int n);
  413.   int fputlong(FILE *fp, long n);
  414.  
  415.  
  416. /********************************************************************
  417. *  Write out the TIF header
  418. ********************************************************************/
  419.   if (bitord == 'm')  fputword(fp, MM_TYPE);
  420.   if (bitord == 'l')  fputword(fp, II_TYPE);
  421.   fputword(fp,42);
  422.   fputlong(fp,8L);
  423.  
  424. /********************************************************************
  425. *  Construct the Image File Directory (IFD)
  426. ********************************************************************/
  427.   fputword(fp, 8);     /* Eight Tags */
  428.  
  429.   fputword(fp, 254);   /* NewSubfileType */
  430.   fputword(fp, 4);     /* Long */
  431.   fputlong(fp, 1L);
  432.   fputlong(fp, 0L);
  433.  
  434.   fputword(fp, 256);   /* ImageWidth */
  435.   fputword(fp, 3);     /* Short */
  436.   fputlong(fp, 1L);    
  437.   if (bitord == 'm')
  438.     fputlong(fp, ns*65536); /* Shift value into the two high order bytes */
  439.   if (bitord == 'l')
  440.     fputlong(fp, ns);
  441.  
  442.   fputword(fp, 257);   /* ImageLength */
  443.   fputword(fp, 3);     /* Short */
  444.   fputlong(fp, 1L);
  445.   if (bitord == 'm')
  446.     fputlong(fp, nl*65536);  /* Shift value into the two high order bytes */
  447.   if (bitord == 'l')
  448.     fputlong(fp, nl);
  449.  
  450.   fputword(fp, 258);   /* BitsPerSample */
  451.   fputword(fp, 3);     /* Short */
  452.   fputlong(fp, 1L);
  453.   if (bitord == 'm') 
  454.     fputlong(fp, 524288L); /* 8 Shifted into the two high order bytes */
  455.   if (bitord == 'l')
  456.     fputlong(fp, 8L);
  457.  
  458.   fputword(fp, 259);   /* Compression */
  459.   fputword(fp, 3);     /* Short */
  460.   fputlong(fp, 1L);
  461.   if (bitord == 'm')
  462.     fputlong(fp, 65536L);    /* No compression */
  463.   if (bitord == 'l')
  464.     fputlong(fp, 1L);
  465.  
  466.   fputword(fp, 262);   /* PhotometricInterpretation */
  467.   fputword(fp, 3);     /* Short */
  468.   fputlong(fp, 1L);
  469.   if (bitord == 'm')
  470.     fputlong(fp, 65536L);  /* 1 Shifted into the two high order bytes */
  471.   if (bitord == 'l')
  472.     fputlong(fp, 1L);
  473.  
  474.   fputword(fp, 273);   /* StripOffsets - Start of image data */
  475.   fputword(fp, 4);     /* Long */
  476.   fputlong(fp, 1L);
  477.   fputlong(fp, 110L);
  478.  
  479.   fputword(fp, 277);   /* SamplesPerPixel */
  480.   fputword(fp, 3);     /* Short */
  481.   fputlong(fp, 1L);
  482.   if (bitord == 'm')
  483.     fputlong(fp, 65536L);
  484.   if (bitord == 'l')
  485.     fputlong(fp, 1L);
  486.  
  487.   fputlong(fp, 0L);
  488.  
  489. /***********************************************************************
  490. *  Write image data
  491. ***********************************************************************/
  492.   /*!!!!!! BE CAREFUL HERE !!!!!!*/
  493.   /* The third argument in fwrite is of type size_t, which under Turbo C
  494.      becomes an unsigned short int (16 bit integer). This means you have
  495.      to write the image data out in blocks of 64K bytes or less (32K is a
  496.      good number).
  497.      Added by Luis Perez 06/29/94. */
  498. #ifdef __TURBOC__
  499.   nblocks = (nl*ns) / BLKSIZE;
  500.   rem = (nl*ns) % BLKSIZE;
  501.   for (j=0; j<nblocks; j++, buf+=BLKSIZE)
  502.      fwrite(buf,1,BLKSIZE,fp);
  503.   if ( rem > 0 )
  504.      fwrite(buf,1,rem,fp);
  505. #else
  506.   fwrite(buf, 1, nl*ns, fp);
  507. #endif
  508.  
  509.   return(0);
  510.  
  511. }
  512.  
  513.  
  514.  
  515.  
  516. int fputword(FILE *fp, short int n)
  517. {
  518.   fwrite(&n, 2, 1,fp);
  519.   
  520. }
  521.  
  522. int fputlong(FILE *fp, long n)
  523. {
  524.   fwrite(&n, 4, 1, fp);
  525.  
  526. }
  527.